package com.nineclock.system.service.impl;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.nineclock.common.entity.PageResult;
import com.nineclock.common.enums.ResponseEnum;
import com.nineclock.common.exception.NcException;
import com.nineclock.common.filter.CurrentUserHolder;
import com.nineclock.common.utils.BeanHelper;
import com.nineclock.system.dto.SysCompanyUserDTO;
import com.nineclock.system.dto.SysDepartmentDTO;
import com.nineclock.system.dto.SysRoleDTO;
import com.nineclock.system.excel.ExcelMember;
import com.nineclock.system.excel.ExcelMemberListener;
import com.nineclock.system.mapper.*;
import com.nineclock.system.pojo.*;
import com.nineclock.system.service.SysCompanyUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Currency;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Transactional
public class SysCompanyUserServiceImpl implements SysCompanyUserService {
    @Autowired(required = false)
    private SysCompanyUserMapper companyUserMapper;
    @Autowired(required = false)
    private SysRoleMapper roleMapper;
    @Autowired
    private SysDepartmentMapper departmentMapper;
    @Autowired
    private SysUserMapper userMapper;
    @Autowired
    private SysCompanyUserRoleMapper companyUserRoleMapper;

    /**
     * 根据系统用户ID、企业id查询员工列表
     *
     * @param userId
     * @param companyId
     * @return
     */
    @Override
    public List<SysCompanyUserDTO> queryCompanyUser(Long userId, Long companyId) {
        //根据用户id，企业id查询员工列表
        LambdaQueryWrapper<SysCompanyUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysCompanyUser::getUserId, userId);
        if (companyId != null) {
            wrapper.eq(SysCompanyUser::getCompanyId, companyId);
        }

        List<SysCompanyUser> sysCompanyUserList = companyUserMapper.selectList(wrapper);
        if (CollectionUtils.isEmpty(sysCompanyUserList)) {
            throw new NcException(ResponseEnum.USER_NOT_JOIN_COMPANY);
        }
        // 数据转换，List<SysCompanyUser> --> List<SysCompanyUserDTO>
        List<SysCompanyUserDTO> companyUserDTOList = BeanHelper.copyWithCollection(sysCompanyUserList, SysCompanyUserDTO.class);
        // 封装员工对应的角色、权限信息
        for (SysCompanyUserDTO sysCompanyUserDTO : companyUserDTOList) {
            // 根据员工id查询对应角色、权限信息
            List<SysRole> sysRoleList = roleMapper.queryRoleByCompanyUserId(sysCompanyUserDTO.getId());
            //数据转换
            List<SysRoleDTO> sysRoleDTOList = BeanHelper.copyWithCollection(sysRoleList, SysRoleDTO.class);
            sysCompanyUserDTO.setRoles(sysRoleDTOList);
            //TODO 同理，需要根据角色id，查询对应的权限信息，并设置
        }
        return companyUserDTOList;
    }

    /**
     * 接口名称：企业管理: 获取企业当前主管理员
     * 接口路径：GET/sys/company/getCurrentAdmin
     */
    @Override
    public SysCompanyUserDTO queryCurrentAdmin() {
        //获取当前企业id
        Long companyId = CurrentUserHolder.get().getCompanyId();
        // 查询主管理员 -  主管理员角色名 ROLE_ADMIN_SYS
        SysCompanyUser sysCompanyAdmin = companyUserMapper.queryMainAdminCompanyUser(companyId);
        if (sysCompanyAdmin == null) {
            throw new NcException(ResponseEnum.COMPANY_ADMIN_NOT_EXISTS);
        }
        return BeanHelper.copyProperties(sysCompanyAdmin, SysCompanyUserDTO.class);
    }

    /**
     * 接口名称：组织架构: 查询组织所有员工
     * 接口路径：GET/sys/organization/members/simple
     */
    @Override
    public List<SysCompanyUserDTO> queryCompanyMemberList() {
        //查询当前企业id
        Long companyId = CurrentUserHolder.get().getCompanyId();
        //根据企业id查询员工
        LambdaQueryWrapper<SysCompanyUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysCompanyUser::getCompanyId, companyId);
        wrapper.eq(SysCompanyUser::getEnable, 1);
        List<SysCompanyUser> sysCompanyUserList = companyUserMapper.selectList(wrapper);
        if (CollectionUtils.isEmpty(sysCompanyUserList)) {
            throw new NcException(ResponseEnum.USER_NOT_FOUND);
        }
        return BeanHelper.copyWithCollection(sysCompanyUserList, SysCompanyUserDTO.class);
    }

    /**
     * 根据员工ID查询企业员工信息
     *
     * @param companyUserId
     */
    @Override
    public SysCompanyUserDTO queryCompanyUserById(Long companyUserId) {
        SysCompanyUser companyUser = companyUserMapper.selectById(companyUserId);
        return BeanHelper.copyProperties(companyUser, SysCompanyUserDTO.class);
    }

    /**
     * 查询所有的企业员工
     *
     * @return
     */
    @Override
    public List<SysCompanyUserDTO> queryAllCompanyUser() {
        LambdaQueryWrapper<SysCompanyUser> lambdaQueryWrapper = new LambdaQueryWrapper<SysCompanyUser>();
        lambdaQueryWrapper.eq(SysCompanyUser::getCompanyId, CurrentUserHolder.get().getCompanyId());
        lambdaQueryWrapper.eq(SysCompanyUser::getEnable, (short) 1);
        List<SysCompanyUser> companyUserList = companyUserMapper.selectList(lambdaQueryWrapper);

        return BeanHelper.copyWithCollection(companyUserList, SysCompanyUserDTO.class);
    }

    /**
     * 组织架构:PC-获取部门成员列表
     *
     * @param page
     * @param pageSize
     * @param departmentId
     * @param keyword
     * @return
     */
    @Override
    public PageResult<SysCompanyUserDTO> queryMembers(Integer page, Integer pageSize, Long departmentId, String keyword) {
        //创建查询对象
        LambdaQueryWrapper<SysCompanyUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysCompanyUser::getCompanyId, CurrentUserHolder.get().getCompanyId());
        if (departmentId != null) {
            //迭代查询子部门
            ArrayList<Long> deptIdList = new ArrayList<>();
            deptIdList.add(departmentId);
            queryAllChildDeparmentIds(deptIdList, departmentId);
            wrapper.in(SysCompanyUser::getDepartmentId, deptIdList);
        }
        if (!StringUtils.isEmpty(keyword)) {
            // and (user_name like xxx or work_number like xxx or mobile like xxx)
            wrapper.and(w -> {
                w.like(SysCompanyUser::getUserName, keyword).
                        or().
                        like(SysCompanyUser::getWorkNumber, keyword).
                        or().
                        like(SysCompanyUser::getMobile, keyword);
            });
        }
        // 创建分页对象
        IPage<SysCompanyUser> ipage = new Page<>(page, pageSize);
        // 执行分页查询
        ipage = companyUserMapper.selectPage(ipage, wrapper);
        // 获取当前页数据
        List<SysCompanyUser> companyUserList = ipage.getRecords();

        if (!CollectionUtils.isEmpty(companyUserList)) {

            List<SysCompanyUserDTO> companyUserDTOList = companyUserList.stream().map(sysCompanyUser -> {
                SysCompanyUserDTO companyUserDTO = BeanHelper.copyProperties(sysCompanyUser, SysCompanyUserDTO.class);
                // 设置一个所属部门对象，接口文档需要
                SysDepartmentDTO departmentDTO = new SysDepartmentDTO();
                departmentDTO.setId(companyUserDTO.getDepartmentId());
                departmentDTO.setName(companyUserDTO.getDepartmentName());
                companyUserDTO.setDepartment(departmentDTO);
                return companyUserDTO;
            }).collect(Collectors.toList());
            return new PageResult<>(ipage.getTotal(), ipage.getPages(), companyUserDTOList);
        }
        return new PageResult<>(ipage.getTotal(), ipage.getPages(), null);
    }

    /**
     * 直接导入员工数据
     *
     * @param excelFile
     */
    @Override
    public void importData(MultipartFile excelFile) throws IOException {
        //健壮性判断
        if (excelFile == null) {
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }
        //解析数据
        EasyExcel.read(excelFile.getInputStream(), ExcelMember.class, new ExcelMemberListener(this)).sheet(0).doRead();
    }

    /**
     * 处理解析完毕之后的员工数据, 进行数据组装及持久化操作
     *
     * @param memberList
     */
    @Override
    public void handleParsedData(List<ExcelMember> memberList) {
        for (ExcelMember excelMember : memberList) {
            //保存系统用户数据
            //判断手机号是否已被注册
            pendingMobileAndEmailAndWorkNumer(excelMember);
            //保存用户数据
            SysUser sysUser = new SysUser();
            sysUser.setUsername(excelMember.getName());
            sysUser.setPassword(new BCryptPasswordEncoder().encode("123456"));
            sysUser.setMobile(excelMember.getMobile());
            sysUser.setEmail(excelMember.getEmail());
            sysUser.setCreateTime(new Date());
            sysUser.setUpdateTime(new Date());
            sysUser.setStatus((short) (excelMember.getEnable().equals("可用") ? 1 : 0));
            sysUser.setLastLoginCompanyId(CurrentUserHolder.get().getCompanyId());
            userMapper.insert(sysUser);
            //保存员工数据
            SysCompanyUser companyUser = saveCompanyUser(excelMember, sysUser);
            //维护企业员工关联角色
            saveCompanyUserRole(companyUser, excelMember);
        }
    }

    /**
     * 根据手机号获取员工信息
     * @param mobile
     * @return
     */
    @Override
    public SysCompanyUserDTO findCompanyUserByMobile(String mobile) {
        //校验参数
        if (StringUtils.isEmpty(mobile)){
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }
        //组装条件查询
        LambdaQueryWrapper<SysCompanyUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysCompanyUser::getCompanyId,CurrentUserHolder.get().getCompanyId());
        wrapper.eq(SysCompanyUser::getMobile,mobile);
        SysCompanyUser companyUser = companyUserMapper.selectOne(wrapper);
        return BeanHelper.copyProperties(companyUser,SysCompanyUserDTO.class);
    }

    /**
     * 根据部门ID集合查询部门下的员工数量
     * @param departmentIds
     * @return
     */
    @Override
    public Integer queryUserCountByDepartmentIds(List<Long> departmentIds) {
        //获取传递过来的部门机器所有子部门
        ArrayList<Long> ids = new ArrayList<Long>();
        ids.addAll(departmentIds);

        for (Long departmentId : departmentIds) {
            this.queryAllChildDeparmentIds(ids, departmentId);
        }
        //组装条件查询用户数量
        LambdaQueryWrapper<SysCompanyUser> companyUserQueryWrapper = new LambdaQueryWrapper<>();
        companyUserQueryWrapper.in(SysCompanyUser::getDepartmentId , ids);
        companyUserQueryWrapper.eq(SysCompanyUser::getEnable, 1);

        Integer count = companyUserMapper.selectCount(companyUserQueryWrapper);
        return count;
    }

    /**
     * 维护企业员工关联角色
     * @param companyUser
     * @param excelMember
     */
    private void saveCompanyUserRole(SysCompanyUser companyUser, ExcelMember excelMember) {
        //根据角色名字查询用户角色id
        LambdaQueryWrapper<SysRole> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysRole::getCompanyId,CurrentUserHolder.get().getCompanyId());
        wrapper.eq(SysRole::getRoleName,excelMember.getRoleName());
        SysRole sysRole = roleMapper.selectOne(wrapper);
        if (sysRole==null){
            SysCompanyUserRole sysCompanyUserRole = new SysCompanyUserRole();
            sysCompanyUserRole.setCompanyUserId(companyUser.getId());
            sysCompanyUserRole.setRoleId(companyUser.getId());
            sysCompanyUserRole.setCompanyId(CurrentUserHolder.get().getCompanyId());
            companyUserRoleMapper.insert(sysCompanyUserRole);
        }
    }
    /**
     * 保存员工数据
     * @param excelMember
     * @param sysUser
     * @return
     */
    private SysCompanyUser saveCompanyUser(ExcelMember excelMember, SysUser sysUser) {
        SysCompanyUser sysCompanyUser =new SysCompanyUser();
        sysCompanyUser.setUserId(sysUser.getId());
        sysCompanyUser.setCompanyId(CurrentUserHolder.get().getCompanyId());
        sysCompanyUser.setCompanyName(CurrentUserHolder.get().getCompanyName());
        sysCompanyUser.setPost(excelMember.getPosition());
        sysCompanyUser.setWorkNumber(excelMember.getWorkNumber());
        sysCompanyUser.setEmail(excelMember.getEmail());
        sysCompanyUser.setOfficeAddress(excelMember.getWorkAddr());
        sysCompanyUser.setTimeEntry(new Date());
        sysCompanyUser.setRemark(excelMember.getDesc());
        sysCompanyUser.setEnable((short) (excelMember.getEnable().equals("可用")?1:0));
        sysCompanyUser.setCreateTime(new Date());
        sysCompanyUser.setUpdateTime(new Date());
        sysCompanyUser.setMobile(excelMember.getMobile());
        sysCompanyUser.setUserName(excelMember.getName());
        //根据部门名称查询部门
        LambdaQueryWrapper<SysDepartment> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysDepartment::getCompanyId,CurrentUserHolder.get().getCompanyId());
        wrapper.eq(SysDepartment::getName,excelMember.getDepartmentName());
        SysDepartment department = departmentMapper.selectOne(wrapper);
        if (department==null){
            sysCompanyUser.setDepartmentId(department.getId());
            sysCompanyUser.setDepartmentName(department.getName());
        }
        companyUserMapper.insert(sysCompanyUser);
        return sysCompanyUser;
    }

    /**
     * 判断手机号是否已被注册
     *
     * @param excelMember
     */
    private void pendingMobileAndEmailAndWorkNumer(ExcelMember excelMember) {
        LambdaQueryWrapper<SysCompanyUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysCompanyUser::getCompanyId, CurrentUserHolder.get().getCompanyId());
        wrapper.and(w -> {
            w.eq(SysCompanyUser::getMobile, excelMember.getMobile())
                    .or()
                    .eq(SysCompanyUser::getEmail, excelMember.getEmail());
        });
        Integer count = companyUserMapper.selectCount(wrapper);
        if (count > 0) {
            throw new NcException(ResponseEnum.USER_MOBILE_EMAIL_EXISTS);
        }

        LambdaQueryWrapper<SysCompanyUser> wrapper1 = new LambdaQueryWrapper<>();
        wrapper1.eq(SysCompanyUser::getCompanyId,CurrentUserHolder.get().getCompanyId());
        wrapper1.eq(SysCompanyUser::getWorkNumber,excelMember.getWorkNumber());
        Integer count1 = companyUserMapper.selectCount(wrapper1);
        if (count1>0){
            throw new NcException(ResponseEnum.WROK_NUM_EXISTS);
        }

    }

    /**
     * 递归查询子部门id集合
     *
     * @param deptIdList
     * @param departmentId
     */
    private void queryAllChildDeparmentIds(ArrayList<Long> deptIdList, Long departmentId) {
        // 查询子部门
        LambdaQueryWrapper<SysDepartment> wrapper = new LambdaQueryWrapper();
        wrapper.eq(SysDepartment::getParentId, departmentId);
        wrapper.eq(SysDepartment::getCompanyId, CurrentUserHolder.get().getCompanyId());

        List<SysDepartment> childDepartmentList = departmentMapper.selectList(wrapper);
        if (!CollectionUtils.isEmpty(childDepartmentList)) {
            for (SysDepartment department : childDepartmentList) {
                deptIdList.add(department.getId());//添加部门id
                //递归查询子部门
                queryAllChildDeparmentIds(deptIdList, department.getId());
            }
        }
    }
}
